package com.apes.fn.scm.retailOrder.service.tc.commission;

import com.alibaba.fastjson.JSONArray;
import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.repository.RetailOrderRepository;
import com.apes.fn.scm.saleReport.model.TurnoverDetails;
import com.apes.fn.scm.saleReport.repository.TurnoverDetailsRepository;
import com.apes.fn.server.servicePlan.model.ServicePlanItem;
import com.apes.fn.server.servicePlan.repository.ServicePlanItemRepository;
import com.apes.fn.server.workOrder.model.MaintenanceOrder;
import com.apes.fn.server.workOrder.repository.MaintenanceOrderRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.Arith;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apestech.framework.json.JSON;
import com.apestech.framework.json.JSONObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @Title: EmployeeCommission
 * @Description: 员工提成
 * @author: ZhengZeXian
 * @create: 2021/8/23 10:28
 */
@Service("employeeCommissionService")
public class EmployeeCommissionService extends DomainService {

    protected static Log logger = LogFactory.getLog(EmployeeCommissionService.class);

    @Autowired
    private EmployeeCommissionDao dao;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    ServicePlanItemRepository servicePlanItemRepository;

    @Autowired
    MaintenanceOrderRepository maintenanceOrderRepository;

    @Autowired
    private TurnoverDetailsRepository turnoverDetailsRepository;

    @Autowired
    private PartyRoleRepository partyRoleRepository;

    /**
     * 根据门店方案明细查找基地方案明细
     *
     * @param id 门店方案明细编码
     * @return ServicePlanItem
     */
    private ServicePlanItem findBaseServicePlanItem(String id) {
        List<ServicePlanItem> list = SpringManager.getBean(ServicePlanItemRepository.class).findAll(JpaDsl.toCriteriaByEq("parentServicePlanItem.id", id, "terminationDate", null));
        if (list.size() == 0) throw new RuntimeException(String.format("根据零售明细单来源行号[%s]获取子服务方案明细行失败！", id));
        if (list.size() > 1) throw new RuntimeException("找到多条子明细行，请检查程序");
        return list.stream().findFirst().get();
    }

    /**
     * 零售单销售提成 正单与负单 (总入口)
     */
    public void execXSTC(SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID", request.getJO().getString("ID"));
        execXSTCZD(param);
        execXSTCFD(param);
    }

    /**
     * 分销单销售提成 基地非定损和基地定损 (总入口)
     */
    public void execFXXSTC(SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));
        execFXSTCFDS(param);
        execFXSTCDS(param);
        execFXSTCFDSFD(param);
        execFXSTCDSFD(param);
    }

    /**
     * 年卡提成 有固定套包提成和无套包 (总入口)
     */
    public void execNKTC(SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));
        execNKTCYTB(param);
        execNKTCWTB(param);
    }

    /**
     * 接送车提成 接车人提成和还车人提成 (总入口)
     */
    public void execJSCTC(SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));
        execJSCTCJC(param);
        execJSCTCSC(param);
    }

    /**
     * 异业开单提成 零售正单和零售负单 (总入口)
     */
    public void execYYKDTC(SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));
        execYYKDTCZD(param);
        execYYKDTCFD(param);
    }

    /**
     * 定损跟踪提成 新系统和老系统 (总入口)
     */
    public void execDSGZTC(SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));
        execNewDSGZTC(param);
//        execOldDSGZTC(param); //老系统目前无需使用
    }

    /**
     * 单据施工提成 零售正单和零售负单和内协负单 (总入口)
     */
    public void execDJSGTC(SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));
        execDJSGTCZD(param);
        execDJSGTCFD(param);
        execDJSGTCNXFD(param);
    }

    /**
     * 单据施工提成整单内协和工单内协正单 (总入口)
     */
    public void execDJSGTCNX(SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));
        execDJSGTCNXZD(param);
    }

    /**
     * 分销单据施工提成 非定损和定损 (总入口)
     */
    public void execFXDJSGTC(SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));
        execFXDJSGTCDS(param);
        execFXDJSGTCDSFD(param);
        execFXDJSGTCFDS(param);
        execFXDJSGTCFDSFD(param);
    }

    /**
     * 执行销售提成正单
     */
    public void execXSTCZD (JSONObject param){
        logger.info("开始执行销售提成正单>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryXSTCZD(param);
        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);
            saveXSTCLog("执行前：" + jsonObject.get("PRODUCT_ID") +jsonObject.toString());
            if(map.get("VOUCHER_ID") == null) throw new RuntimeException("凭证生成异常"+ map.get("PRODUCT_ID"));

            logger.info("第一步：判断是否要计算提成(体系外合作单位业务)");
            if (map.get("OUT_SYSTEM_BUSINESS").toString().equals("1")){
                if (!dao.existXSTCKD(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;
            }

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existXSTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：取TC01销售提成规则");
            JSONObject TC01 = getStrategy(map, "TC01");
            /** 无取到销售提成策略 不执行后面的操作 */
            if (TC01.get("sys_break") != null && (TC01.get("sys_break").equals("1") && !map.get("OUT_SYSTEM_BUSINESS").toString().equals("1"))){
                logger.info("第二步：未取到TC01销售提成规则即将退出！！！");
                //回写销售员到营业额明细
                writeBackCommission(map,"saleCommission",false,map.get("RETAIL_ORDER_ID").toString());
                return;
            }


            logger.info("第三步：取考核成本价条件策略");
            JSONObject KHCBJ = getStrategy(map, "KHCBJ");


            map.putAll(TC01);
            map.put("CLH",map.get("C_ID"));
            map.putAll(KHCBJ);


            logger.info("第四步：计算考核成本价");
            map.put("ASSESSMENT_COST_PRICE",execExpress(TCFormula.XSTC_KHCBJ,map));

            logger.info("第五步：计算成本金额");
            map.put("PROFIT_AMT", execExpress(TCFormula.XSTC_CBJE,map));
            map.put("REFER_TAX", execExpress("ASSESSMENT_COST_PRICE != 0 ? ASSESSMENT_COST_PRICE : REFER_TAX",map));

            logger.info("第六步：计算提成比例/固定金额");
            map.put("TCBL_JE", execExpress(TCFormula.XSTC_TCBL_JE,map));

            logger.info("第七步：计算提成金额");
            map.put("TCJE",execExpress(TCFormula.XSTC_TCJE,map));

            //方案类型为整单内协 门店 和 基地 各拿百分之50的提成
            if (Objects.equals(map.get("PLAN_TYPE"),"allAssist")){
//                map.put("TCBL_JE",execExpress("return TCBL_JE/2",map));
                map.put("TCJE",execExpress("return TCJE/2;",map));

                JSONObject insertData = null;
                try {
                    insertData = new JSONObject(new JSONObject(map).toString());
                } catch (Exception e) {
                    throw new RuntimeException("计算整单内协基地销售提成转换JSON报错");
                }

                ServicePlanItem servicePlanItem = findBaseServicePlanItem((String) map.get("SERVICE_PLAN_ITEM_ID"));

                insertData.put("SOURCE",servicePlanItem.getServicePlan().getId());
                insertData.put("MAIN_SALESMAN",servicePlanItem.getMainSaler() == null ? null : servicePlanItem.getMainSaler().getId());
                insertData.put("SUB_SALESMAN",servicePlanItem.getSupSaler() == null ? null : servicePlanItem.getSupSaler().getId());
                insertData.put("TJRQ",(Date)map.get("TJRQ"));
                insertData.put("DEPT_ID",servicePlanItem.getServicePlan().getBelongDept().getId());
                insertData.put("COMPANY_ID",servicePlanItem.getServicePlan().getBelongDept().getCompany().getId());
                insertData.put("ID",dao.queryXSTCID(jsonObject).getJSONObject(0).getString("ID"));

                logger.info("第八步：计算主销提成金额");
                insertData.put("MAIN_SALESMAN_TCJE",execExpress(TCFormula.XSTC_ZXTCJE,insertData));

                logger.info("第九步：计算辅销提成金额");
                insertData.put("SUB_SALESMAN_TCJE",execExpress(TCFormula.XSTC_FXTCJE,insertData));

                logger.info("执行写入销售提成参数" + insertData.toString());
                saveXSTCLog("执行后整单内协：" + jsonObject.get("PRODUCT_ID") +jsonObject.toString());
                dao.insertXSTC(insertData);
            }

            logger.info("第八步：计算主销提成金额");
            map.put("MAIN_SALESMAN_TCJE",execExpress(TCFormula.XSTC_ZXTCJE,map));

            logger.info("第九步：计算辅销提成金额");
            map.put("SUB_SALESMAN_TCJE",execExpress(TCFormula.XSTC_FXTCJE,map));


            jsonObject = new JSONObject(map);

            logger.info("执行写入销售提成参数" + jsonObject.toString());
            saveXSTCLog("执行后：" + jsonObject.get("PRODUCT_ID") +jsonObject.toString());
            dao.insertXSTC(jsonObject);
            //回写提成到营业额明细
            writeBackCommission(map,"saleCommission",true,map.get("RETAIL_ORDER_ID").toString());
        });
    }

    /**
     * 执行销售提成负单
     */
    public void execXSTCFD (JSONObject param){
        logger.info("开始执行销售提成负单>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = new ArrayList<>();

        maps.addAll(dao.queryXSTCFD(param));
        maps.addAll(dao.queryXSTCFD_EBY(param));

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);
            saveXSTCLog("执行前：" + jsonObject.get("PRODUCT_ID") +jsonObject.toString());
            logger.info("第一步：判断是否要计算提成");
            if (!dao.existXSTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            /** 无取到原单据 不执行后面的操作 */
            if(map.get("OLD_SALE_ID") == null){
                logger.info("第一步：未取到原单据即将退出！！！");
                //回写销售员到营业额明细
                writeBackCommission(map,"saleCommission",false,map.get("RETAIL_ORDER_ID").toString());
                return;
            }
            logger.info("第二步：获取原提成金额");
            map.put("OLE_TCJE",checkAmtField(dao.queryXSTCFDOLDTCJE(jsonObject),"OLE_TCJE"));

            logger.info("第三步：获取原销售金额");
            map.put("OLE_SALE_AMT",checkAmtField(dao.queryXSTCFDYXXJE(jsonObject),"OLE_SALE_AMT"));

            /** 无取到原单据提成 不执行后面的操作 */
            if (Double.parseDouble(map.get("OLE_TCJE").toString()) == 0 && Double.parseDouble(map.get("OLE_SALE_AMT").toString()) == 0){
                logger.info("第二步：未取到原单据提成即将退出！！！");
                //回写销售员到营业额明细
                writeBackCommission(map,"saleCommission",false,map.get("RETAIL_ORDER_ID").toString());
                return;
            }

            logger.info("第四步：计算提成金额");
            map.put("TCJE",execExpress(TCFormula.XSTC_FD_TCJE,map));


            //方案类型为整单内协 门店 和 基地 各拿百分之50的提成
            if (Objects.equals(map.get("PLAN_TYPE"),"allAssist")){
                map.put("TCJE",execExpress("return TCJE/2;",map));

                JSONObject insertData = null;
                try {
                    insertData = new JSONObject(new JSONObject(map).toString());
                } catch (Exception e) {
                    throw new RuntimeException("计算整单内协基地销售提成转换JSON报错");
                }
                ServicePlanItem servicePlanItem = findBaseServicePlanItem((String) map.get("SERVICE_PLAN_ITEM_ID"));
                insertData.put("SOURCE",servicePlanItem.getServicePlan().getId());
                insertData.put("MAIN_SALESMAN",servicePlanItem.getMainSaler() == null ? null : servicePlanItem.getMainSaler().getId());
                insertData.put("SUB_SALESMAN",servicePlanItem.getSupSaler() == null ? null : servicePlanItem.getSupSaler().getId());
                insertData.put("DEPT_ID",servicePlanItem.getServicePlan().getBelongDept().getId());
                insertData.put("COMPANY_ID",servicePlanItem.getServicePlan().getBelongDept().getCompany().getId());
                insertData.put("TJRQ",(Date)map.get("TJRQ"));
                insertData.put("ID",dao.queryXSTCID(jsonObject).getJSONObject(0).getString("ID"));

                logger.info("第八步：计算主销提成金额");
                insertData.put("MAIN_SALESMAN_TCJE",execExpress(TCFormula.XSTC_ZXTCJE,insertData));

                logger.info("第九步：计算辅销提成金额");
                insertData.put("SUB_SALESMAN_TCJE",execExpress(TCFormula.XSTC_FXTCJE,insertData));

                logger.info("执行写入销售提成参数" + insertData.toString());
                saveXSTCLog("执行后整单内协：" + jsonObject.get("PRODUCT_ID") +jsonObject.toString());
                dao.insertXSTC(insertData);
            }

            logger.info("第五步：计算主销提成金额");
            map.put("MAIN_SALESMAN_TCJE",execExpress(TCFormula.XSTC_ZXTCJE,map));

            logger.info("第六步：计算辅销提成金额");
            map.put("SUB_SALESMAN_TCJE",execExpress(TCFormula.XSTC_FXTCJE,map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入销售提成参数" + jsonObject.toString());
            saveXSTCLog("执行后：" + jsonObject.get("PRODUCT_ID") +jsonObject.toString());
            dao.insertXSTC(jsonObject);
            //回写提成到营业额明细
            writeBackCommission(map,"saleCommission",true,map.get("RETAIL_ORDER_ID").toString());
        });
    }

    /**
     * 执行分销销售提成_基地非定损
     */
    public void execFXSTCFDS (JSONObject param){
        logger.info("开始执行分销销售提成基地非定损>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryFXXSTC_FDS(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existXSTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：取TC01销售提成规则");
            JSONObject TC01 = getStrategy(map, "TC01");
            /** 无取到销售提成策略 不执行后面的操作 */
            if (TC01.get("sys_break") == null ? false : TC01.get("sys_break").equals("1")){
                logger.info("第二步：未取到TC01销售提成规则即将退出！！！");
                //回写销售员到营业额明细
                writeBackCommission(map,"saleCommission",false,map.get("RETAIL_ORDER_ID").toString());
                return;
            }

            logger.info("第三步：取考核成本价条件策略");
            JSONObject KHCBJ = getStrategy(map, "KHCBJ");


            map.putAll(TC01);
            map.put("CLH",map.get("C_ID"));
            map.putAll(KHCBJ);


            logger.info("第四步：计算考核成本价");
            map.put("ASSESSMENT_COST_PRICE",execExpress(TCFormula.FXXSTC_KHCBJ,map));

            logger.info("第五步：计算成本金额");
            map.put("PROFIT_AMT", execExpress(TCFormula.FXXSTC_CBJE,map));
            map.put("REFER_TAX", execExpress("ASSESSMENT_COST_PRICE != 0 ? ASSESSMENT_COST_PRICE : REFER_TAX",map));

            logger.info("第六步：计算提成金额");
            map.put("TCJE",execExpress(TCFormula.FXXSTCFDS_TCJE,map));

            logger.info("第七步：计算主销提成金额");
            map.put("MAIN_SALESMAN_TCJE",execExpress(TCFormula.XSTC_ZXTCJE,map));

            logger.info("第八步：计算辅销提成金额");
            map.put("SUB_SALESMAN_TCJE",execExpress(TCFormula.XSTC_FXTCJE,map));


            jsonObject = new JSONObject(map);
            logger.info("执行写入销售提成参数" + jsonObject.toString());
            dao.insertXSTC(jsonObject);
            //回写提成到营业额明细
            writeBackCommission(map,"saleCommission",true,map.get("RETAIL_ORDER_ID").toString());
        });
    }

    /**
     * 执行分销销售提成_基地非定损负单
     */
    public void execFXSTCFDSFD (JSONObject param){
        logger.info("开始执行分销销售提成基地非定损负单>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryFXXSTC_FDSFD(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existXSTCFXFD(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第五步：计算提成金额");
            map.put("TCJE",execExpress("OLD_TCJE/OLD_SALE_QTY * SALE_QTY",map));

            logger.info("第七步：计算主销提成金额");
            map.put("MAIN_SALESMAN_TCJE",execExpress(TCFormula.XSTC_ZXTCJE,map));

            logger.info("第八步：计算辅销提成金额");
            map.put("SUB_SALESMAN_TCJE",execExpress(TCFormula.XSTC_FXTCJE,map));

            jsonObject = new JSONObject(map);
            logger.info("执行写入销售提成参数" + jsonObject.toString());
            dao.insertXSTC(jsonObject);
            //回写提成到营业额明细
            writeBackCommission(map,"saleCommission",true,map.get("RETAIL_ORDER_ID").toString());
        });
    }


    /**
     * 执行分销销售提成_基地定损
     */
    public void execFXSTCDS (JSONObject param){
        logger.info("开始执行分销销售提成基地定损>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryFXXSTC_DS(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成(体系外合作单位业务)");
            if (map.get("OUT_SYSTEM_BUSINESS").toString().equals("1")){
                if (!dao.existXSTCKD(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;
            }

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existXSTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            jsonObject.put("SYS_NO_CHECK", "BRAND_ID");

            logger.info("第二步：取TC01销售提成规则");
            JSONObject TC01 = getStrategy(map, "TC01");
            /** 无取到销售提成策略 不执行后面的操作 */
            if (TC01.get("sys_break") == null ? false : TC01.get("sys_break").equals("1") && !map.get("OUT_SYSTEM_BUSINESS").toString().equals("1")){
                logger.info("第二步：未取到TC01销售提成规则即将退出！！！");
                //回写销售员到营业额明细
                writeBackCommission(map,"saleCommission",false,map.get("RETAIL_ORDER_ID").toString());
                return;
            }

            logger.info("第三步：取考核成本价条件策略");
            JSONObject KHCBJ = getStrategy(map, "KHCBJ");


            map.putAll(TC01);
            map.put("CLH",map.get("C_ID"));
            map.putAll(KHCBJ);


            logger.info("第四步：计算考核成本价");
            map.put("ASSESSMENT_COST_PRICE",execExpress(TCFormula.FXXSTC_KHCBJ,map));

            logger.info("第五步：计算成本金额");
            map.put("PROFIT_AMT", execExpress(TCFormula.FXXSTC_CBJE,map));
            map.put("REFER_TAX", execExpress("ASSESSMENT_COST_PRICE != 0 ? ASSESSMENT_COST_PRICE : REFER_TAX",map));

            logger.info("第六步：计算提成金额");
            map.put("TCJE",execExpress(TCFormula.FXXSTCDS_TCJE,map));

            logger.info("第七步：计算主销提成金额");
            map.put("MAIN_SALESMAN_TCJE",execExpress(TCFormula.XSTC_ZXTCJE,map));

            logger.info("第八步：计算辅销提成金额");
            map.put("SUB_SALESMAN_TCJE",execExpress(TCFormula.XSTC_FXTCJE,map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入销售提成参数" + jsonObject.toString());
            dao.insertXSTC(jsonObject);
            //回写提成到营业额明细
            writeBackCommission(map,"saleCommission",true,map.get("RETAIL_ORDER_ID").toString());
        });
    }


    /**
     * 执行分销销售提成_基地定损负单
     */
    public void execFXSTCDSFD (JSONObject param){
        logger.info("开始执行分销销售提成基地定损负单>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryFXXSTC_DSFD(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成(体系外合作单位业务)");
            if (map.get("OUT_SYSTEM_BUSINESS").toString().equals("1")){
                if (!dao.existXSTCFXFD(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;
            }

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existXSTCFXFD(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            jsonObject.put("SYS_NO_CHECK", "BRAND_ID");

            logger.info("第五步：计算提成金额");
            map.put("TCJE",execExpress("OLD_TCJE/OLD_SALE_QTY * SALE_QTY",map));

            logger.info("第七步：计算主销提成金额");
            map.put("MAIN_SALESMAN_TCJE",execExpress(TCFormula.XSTC_ZXTCJE,map));

            logger.info("第八步：计算辅销提成金额");
            map.put("SUB_SALESMAN_TCJE",execExpress(TCFormula.XSTC_FXTCJE,map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入销售提成参数" + jsonObject.toString());
            dao.insertXSTC(jsonObject);
            //回写提成到营业额明细
            writeBackCommission(map,"saleCommission",true,map.get("RETAIL_ORDER_ID").toString());
        });
    }

    /**
     * 执行年卡套包提成_有套包提成
     */
    public void execNKTCYTB (JSONObject param){
        logger.info("开始执行年卡提成有固定套包提成>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryNKTC_YTB(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existNKTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：计算主销提成金额");
            map.put("MAIN_SALESMAN_TCJE",execExpress(TCFormula.NKTCYTB_ZXTCJE,map));

            logger.info("第三步：计算辅销提成金额");
            map.put("SUB_SALESMAN_TCJE",execExpress(TCFormula.NKTCYTB_FXTCJE,map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入年卡提成参数" + jsonObject.toString());
            dao.insertNKTC(jsonObject);
        });
    }

    /**
     * 执行年卡套包提成_无套包提成
     */
    public void execNKTCWTB (JSONObject param){
        logger.info("开始执行年卡提成无固定套包提成>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryNKTC_WTB(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否有原单");
            if (map.get("SOURCE") == null) return;

            logger.info("第二步：判断是否要计算提成");
            if (!dao.existNKXSTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第三步：获取原提成金额");
            map.put("OLE_TCJE",checkAmtField(dao.queryNKTCWTBOLDTCJE(jsonObject),"OLE_TCJE"));

            logger.info("第四步：获取原销售金额");
            map.put("OLE_XSJE",checkAmtField(dao.queryNKTCWTBOLDXSJE(jsonObject),"OLE_XSJE"));

            logger.info("第五步：计算提成金额");
            map.put("OLE_XSJE",execExpress(TCFormula.NKTCWTB_TCJE,map));

            logger.info("第七步：计算主销提成金额");
            map.put("MAIN_SALESMAN_TCJE",execExpress(TCFormula.NKTCYTB_ZXTCJE,map));

            logger.info("第七步：计算辅销提成金额");
            map.put("SUB_SALESMAN_TCJE",execExpress(TCFormula.NKTCYTB_FXTCJE,map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入销售提成参数" + jsonObject.toString());
            dao.insertNKTC(jsonObject);
        });
    }

    /**
     * 执行接送车提成_接车人提成
     */
    public void execJSCTCJC (JSONObject param){
        logger.info("开始执行接送车提成接车人提成>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryJSCTC_JC(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existJSCTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：计算提成金额");
            map.put("TC_AMT",execExpress("(COMMISSION_FLAG == 1 && ORDER_TYPE != 'repair') ? 5 : 0",map));

            jsonObject = new JSONObject(map);
            jsonObject.put("COMMISSION_FLAG",Integer.parseInt(map.get("COMMISSION_FLAG").toString()));

            logger.info("执行写入接送车提成参数" + jsonObject.toString());
            dao.insertJSCTC(jsonObject);
        });
    }

    /**
     * 执行接送车提成_送车人提成
     */
    public void execJSCTCSC (JSONObject param){
        logger.info("开始执行接送车提成送车人提成>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryJSCTC_SC(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existJSCTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：计算提成金额");
            map.put("TC_AMT",execExpress("(COMMISSION_FLAG == 1 && ORDER_TYPE != 'repair') ? 5 : 0",map));

            jsonObject = new JSONObject(map);
            jsonObject.put("COMMISSION_FLAG",Integer.parseInt(map.get("COMMISSION_FLAG").toString()));

            logger.info("执行写入接送车提成参数" + jsonObject.toString());
            dao.insertJSCTC(jsonObject);
        });
    }

    /**
     * 执行开单提成_内协开单提成
     */
    public void execNXKDTC (SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));

        logger.info("开始查询>>>>>>>>>>>>>>>>>>>" + request.getJO().getString("ID"));
        List<Map> maps = dao.queryNXKDTC(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existKDTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第一步：判断是否存在工单内协标记");
            if (!dao.existNXKDGDNBJ(jsonObject).getJSONObject(0).get("GDCZBJ").toString().equals("0")) return;

            logger.info("第三步：计算提成金额");
            if(!"repair".equals(jsonObject.getString("ORDER_TYPE")) ){
                map.put("TC_AMT",BigDecimal.valueOf(5));
            }else {
                map.put("TC_AMT",BigDecimal.valueOf(0));
            }
            jsonObject = new JSONObject(map);

            logger.info("执行写入开单提成参数" + jsonObject.toString());
            dao.insertKDTC(jsonObject);
        });
    }

    /**
     * 执行开单提成_异业开单提成零售正单
     */
    public void execYYKDTCZD (JSONObject param){
        logger.info("开始执行开单提成_异业开单提成零售正单>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryYYKDTC_ZD(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existYYKDTCZD(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：取TC06异业开单提成规则");
            JSONObject TC06 = getStrategy(map, "TC06");
            /** 无取到销售提成策略 不执行后面的操作 */
            if (TC06.get("sys_break") == null ? false : TC06.get("sys_break").equals("1")){
                logger.info("第二步：未取到TC06异业开单提成规则即将退出！！！");
                return;
            }
            map.putAll(TC06);

            logger.info("第三步：计算提成金额");
            map.put("TC_AMT",execExpress("return T001;",map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入异业开单提成参数" + jsonObject.toString());
            dao.insertKDTC(jsonObject);
        });
    }

    /**
     * 执行开单提成_异业开单提成零售负单
     */
    public void execYYKDTCFD (JSONObject param){
        logger.info("开始执行开单提成_异业开单提成零售负单>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryYYKDTC_FD(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否有原单");
            if (map.get("OLD_RETAIL_ORDER_ID") == null) return;

            logger.info("第二步：判断是否要计算提成");
            if (!dao.existYYKDTCZD(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第三步：获取原提成金额");
            map.put("OLE_TCJE",checkAmtField(dao.queryYYKDTCOLDTCJE(jsonObject),"OLE_TCJE"));

            logger.info("第四步：计算提成金额");
            map.put("TC_AMT",execExpress(TCFormula.YYKDTCFD_TCJE,map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入异业开单提成参数" + jsonObject.toString());
            dao.insertKDTC(jsonObject);
        });
    }

    /**
     * 执行开单提成_代勘提成_完成代勘
     */
    public void execDKTCWCDK (SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));

        logger.info("开始查询>>>>>>>>>>>>>>>>>>>" + request.getJO().getString("ID"));
        List<Map> maps = dao.queryDKTC_WCDK(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existDKTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：取TC07代勘提成规则");
            JSONObject TC07 = getStrategy(map, "TC07");
            /** 无取到代勘提成策略 不执行后面的操作 */
            if (TC07.get("sys_break") == null ? false : TC07.get("sys_break").equals("1")){
                logger.info("第二步：未取到TC07代勘提成规则即将退出！！！");
                return;
            }
            map.putAll(TC07);

            logger.info("第三步：计算提成金额");
            map.put("TC_AMT",execExpress("return T001;",map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入代勘提成参数" + jsonObject.toString());
            dao.insertKDTC(jsonObject);
        });
    }

    /**
     * 执行开单提成_代勘提成_定损完成
     */
    public void execDKTCDSWC (SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));

        logger.info("开始查询>>>>>>>>>>>>>>>>>>>" + request.getJO().getString("ID"));
        List<Map> maps = dao.queryDKTC_DSWC(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existDKTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：取TC07代勘提成规则");
            JSONObject TC07 = getStrategy(map, "TC07");
            /** 无取到代勘提成策略 不执行后面的操作 */
            if (TC07.get("sys_break") == null ? false : TC07.get("sys_break").equals("1")){
                logger.info("第二步：未取到TC07代勘提成规则即将退出！！！");
                return;
            }
            map.putAll(TC07);

            logger.info("第三步：计算提成金额");
            map.put("TC_AMT",execExpress("return T002;",map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入代勘提成参数" + jsonObject.toString());
            dao.insertKDTC(jsonObject);
        });
    }

    /**
     * 执行开单提成_代勘提成_定损完成(老系统定时任务调用)
     * 根据 DATE_START DATE_END 日期调用
     */
    public void execDKTCDSWCOLD (SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("DATE_START",request.getMap().get("DATE_START"));
        param.put("DATE_END",request.getMap().get("DATE_END"));

        logger.info("开始查询>>>>>>>>>>>>>>>>>>>" + param.get("DATE_START") + param.get("DATE_END"));
        List<Map> maps = dao.queryDKTC_DSWC_OLD(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existDKTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：取TC07代勘提成规则");
            JSONObject TC07 = getStrategy(map, "TC07");
            /** 无取到代勘提成策略 不执行后面的操作 */
            if (TC07.get("sys_break") == null ? false : TC07.get("sys_break").equals("1")){
                logger.info("第二步：未取到TC07代勘提成规则即将退出！！！");
                return;
            }
            map.putAll(TC07);

            logger.info("第三步：计算提成金额");
            map.put("TC_AMT",execExpress("return T002;",map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入代勘提成参数" + jsonObject.toString());
            dao.insertKDTC(jsonObject);
        });
    }

    /**
     * 执行定损销售提成_接案介绍费
     */
    public void execDSXSTC (SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));

        logger.info("开始查询>>>>>>>>>>>>>>>>>>>" + request.getJO().getString("ID"));
        List<Map> maps = dao.queryDSXSTC(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existDSXSETC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：计算提成金额");
            map.put("TCJE",execExpress("return AMOUNT*0.1;",map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入参数" + jsonObject.toString());
            dao.insertDSXSETC(jsonObject);
        });
    }

    /**
     * 执行定损销售提成_定损服务费
     */
    public void execDSFWTC (SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));

        logger.info("开始查询>>>>>>>>>>>>>>>>>>>" + request.getJO().getString("ID"));
        List<Map> maps = dao.queryDSFWTC(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existDSFWTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：计算提成金额");
            map.put("TCJE",execExpress("return AMOUNT*0.05;",map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入参数" + jsonObject.toString());
            dao.insertDSFWTC(jsonObject);
        });
    }

    /**
     * 执行定损销售提成_车险提成规则
     */
    public void execCXTC (SimpleRequest request){
        JSONObject param = new JSONObject();
        param.put("BILL_ID",request.getJO().getString("ID"));

        logger.info("开始查询>>>>>>>>>>>>>>>>>>>" + request.getJO().getString("ID"));
        List<Map> maps = dao.queryCXTC(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existCXTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            jsonObject = new JSONObject(map);

            logger.info("执行写入参数" + jsonObject.toString());
            dao.insertCXTC(jsonObject);
        });
    }

    /**
     * 执行定损销售提成_定损跟踪提成_新系统
     */
    public void execNewDSGZTC (JSONObject param){
        logger.info("开始执行定损销售提成定损跟踪提成新系统>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));

        List<Map> maps = dao.queryNewDSGZTC(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existNewDSGZTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            jsonObject = new JSONObject(map);

            logger.info("执行写入参数" + jsonObject.toString());
            dao.insertNewDSGZTC(jsonObject);
        });
    }

    /**
     * 执行定损销售提成_定损跟踪提成_老系统
     */
    public void execOldDSGZTC (JSONObject param){
        logger.info("开始执行定损销售提成定损跟踪提成老系统>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryOldDSGZTC(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existOldDSGZTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            jsonObject = new JSONObject(map);

            logger.info("执行写入参数" + jsonObject.toString());
            dao.insertOldDSGZTC(jsonObject);
        });
    }

    /**
     * 执行单据施工提成零售正单
     */
    public void execDJSGTCZD (JSONObject param){
        logger.info("开始执行单据施工提成零售正单>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        String bill_id = param.getString("BILL_ID");
        RetailOrder retailOrder = SpringManager.getBean(RetailOrderRepository.class).findOne(bill_id);
        retailOrder.getSaleItems().stream().filter(retailOrderItem -> retailOrderItem.getOriginnumber() != null)
                .map(retailOrderItem -> servicePlanItemRepository.findOne(retailOrderItem.getOriginnumber()))
                .filter(Objects::nonNull).filter(servicePlanItem -> "1".equals(servicePlanItem.getCrossOrderWorkMark()))
                .forEach(servicePlanItem -> {
                    MaintenanceOrder maintenanceOrder;
                    if (servicePlanItem.getRelevanceWorkOrder() != null) {
                        maintenanceOrder = maintenanceOrderRepository.findOne(servicePlanItem.getRelevanceWorkOrder());
                    } else {
                        maintenanceOrder = maintenanceOrderRepository.findByServicePlanItemAndBusinessType(servicePlanItem,"common");
                    }
                    List<ServicePlanItem> servicePlanItems = servicePlanItemRepository.findByRelevanceWorkOrder(maintenanceOrder.getId());
                    servicePlanItems.stream()
                            .filter(ser1 -> !"termination".equals(ser1.getServicePlan().getState()))
                            .filter(ser -> ser.getServicePlan().getReceivableDate() == null)
                            .forEach(ser -> {
                                throw new RuntimeException("原单:"+servicePlanItem.getServicePlan().getId()+"明细:"+servicePlanItem.getId() + "属于跨单,跨单:"+ser.getServicePlan().getId()+"明细:"+ser.getId()+"还未完成");
                            });
                });
        List<Map> maps = dao.queryDJSGTC_ZD(param);
        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            saveSGTCLog("执行前:" + jsonObject.get("PRODUCT_ID") +jsonObject.toString());
            logger.info("第一步：判断是否要计算提成");
            if (!dao.existDJSGTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：取TC03施工提成规则");
            JSONObject TC03 = getStrategy(map, "TC03");
            //检查策略是否有取到 没有初始化字段默认值为0
            dao.checkField(TC03,"T101","T102");

            logger.info("第三步：取TC04工序提成规则");
            JSONObject TC04 = getStrategy(map, "TC04");
            //检查策略是否有取到 没有初始化字段默认值为0
            dao.checkField(TC04,"T111","T121","T112","T122","T113","T123","T114","T124");

            map.putAll(TC03);
            map.putAll(TC04);

            logger.info("第四步：判断是否要计算提成");
            if (map.get("T101").equals(0) && map.get("T102").equals(0) && map.get("T111").equals(0) && map.get("T121").equals(0)
                    && map.get("T112").equals(0) && map.get("T122").equals(0) && map.get("T113").equals(0)
                    && map.get("T123").equals(0) && map.get("T114").equals(0) && map.get("T124").equals(0)){
                //回写施工人到营业额明细
                writeBackCommission(map,"workCommission",false,map.get("RETAIL_ORDER_ID").toString());
                return;
            }

            logger.info("第五步：计算工序1提成");
            map.put("TCJE1",execExpress(TCFormula.DJSGTCZD_TCJE1,map));

            logger.info("第六步：计算工序1提成比例/固定金额");
            map.put("TCBL_JE1",execExpress(TCFormula.DJSGTCZD_TCBL_JE1,map));

            logger.info("第七步：计算工序2提成");
            map.put("TCJE2",execExpress(TCFormula.DJSGTCZD_TCJE2,map));

            logger.info("第八步：计算工序2提成比例/固定金额");
            map.put("TCBL_JE2",execExpress(TCFormula.DJSGTCZD_TCBL_JE2,map));

            logger.info("第九步：计算工序3提成");
            map.put("TCJE3",execExpress(TCFormula.DJSGTCZD_TCJE3,map));

            logger.info("第十步：计算工序3提成比例/固定金额");
            map.put("TCBL_JE3",execExpress(TCFormula.DJSGTCZD_TCBL_JE3,map));

            logger.info("第十一步：计算工序4提成");
            map.put("TCJE4",execExpress(TCFormula.DJSGTCZD_TCJE4,map));

            logger.info("第十二步：计算工序4提成比例/固定金额");
            map.put("TCBL_JE4",execExpress(TCFormula.DJSGTCZD_TCBL_JE4,map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入单据施工提成参数" + jsonObject.toString());
            saveSGTCLog("执行后:" + jsonObject.get("PRODUCT_ID") +jsonObject.toString());
            dao.insertDJSGTC(jsonObject);
            //回写提成到营业额明细
            writeBackCommission(map,"workCommission",true,map.get("RETAIL_ORDER_ID").toString());
            logger.info("开始计算人员施工提成");
            try {
                execRYSGTC(map);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        });
    }

    /**
     * 执行单据施工提成零售负单
     */
    public void execDJSGTCFD (JSONObject param){
        logger.info("开始执行单据施工提成零售负单>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));

        List<Map> maps = dao.queryDJSGTC_FD(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);
            saveSGTCLog("执行前:" + jsonObject.get("PRODUCT_ID") +jsonObject.toString());
            logger.info("第一步：判断是否要计算提成");
            if (!dao.existDJSGTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：取TC03施工提成规则");
            JSONObject TC03 = getStrategy(map, "TC03");
            //检查策略是否有取到 没有初始化字段默认值为0
            dao.checkField(TC03,"T101","T102");

            logger.info("第三步：取TC04工序提成规则");
            JSONObject TC04 = getStrategy(map, "TC04");
            //检查策略是否有取到 没有初始化字段默认值为0
            dao.checkField(TC04,"T111","T121","T112","T122","T113","T123","T114","T124");

            map.putAll(TC03);
            map.putAll(TC04);

            logger.info("第四步：判断是否要计算提成");
            if (map.get("T101").equals(0) && map.get("T102").equals(0) && map.get("T111").equals(0) && map.get("T121").equals(0)
                    && map.get("T112").equals(0) && map.get("T122").equals(0) && map.get("T113").equals(0)
                    && map.get("T123").equals(0) && map.get("T114").equals(0) && map.get("T124").equals(0)){
                //回写施工人到营业额明细
                writeBackCommission(map,"workCommission",false,map.get("RETAIL_ORDER_ID").toString());
                return;
            }

            logger.info("第五步：计算工序1提成");
            map.put("TCJE1",execExpress(TCFormula.DJSGTCFD_TCJE1,map));

            logger.info("第六步：计算工序2提成");
            map.put("TCJE2",execExpress(TCFormula.DJSGTCFD_TCJE2,map));

            logger.info("第七步：计算工序3提成");
            map.put("TCJE3",execExpress(TCFormula.DJSGTCFD_TCJE3,map));

            logger.info("第八步：计算工序4提成");
            map.put("TCJE4",execExpress(TCFormula.DJSGTCFD_TCJE4,map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入单据施工提成参数" + jsonObject.toString());
            saveSGTCLog("执行后:" + jsonObject.get("PRODUCT_ID") +jsonObject.toString());
            dao.insertDJSGTC(jsonObject);
            //回写提成到营业额明细
            writeBackCommission(map,"workCommission",true,map.get("RETAIL_ORDER_ID").toString());
            logger.info("开始计算人员施工提成");
            try {
                execRYSGTC(map);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        });
    }



    /**
     * 执行单据施工提成 整单内协和工单内协正单
     */
    public void execDJSGTCNXZD (JSONObject param){
        logger.info("开始执行单据施工提成整单内协和工单内协正单>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryDJSGTC_NXZD(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existDJSGTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：取TC03施工提成规则");
            JSONObject TC03 = getStrategy(map, "TC03");
            //检查策略是否有取到 没有初始化字段默认值为0
            dao.checkField(TC03,"T101","T102");

            logger.info("第三步：取TC04工序提成规则");
            JSONObject TC04 = getStrategy(map, "TC04");
            //检查策略是否有取到 没有初始化字段默认值为0
            dao.checkField(TC04,"T111","T121","T112","T122","T113","T123","T114","T124");

            map.putAll(TC03);
            map.putAll(TC04);

            logger.info("第四步：判断是否要计算提成");
            if (map.get("T101").equals(0) && map.get("T102").equals(0) && map.get("T111").equals(0) && map.get("T121").equals(0)
                    && map.get("T112").equals(0) && map.get("T122").equals(0) && map.get("T113").equals(0)
                    && map.get("T123").equals(0) && map.get("T114").equals(0) && map.get("T124").equals(0)){
                //回写施工人到营业额明细
//                TurnoverDetails turnoverDetails = turnoverDetailsRepository.findByOriginAndOriginItem(map.get("RETAIL_ORDER_ID").toString(), map.get("RETAIL_ITEM_ID").toString());
//                if(turnoverDetails != null){
//                turnoverDetails.setWorker(map.get("THE_WORKER").toString());
//                turnoverDetailsRepository.saveAndFlush(turnoverDetails);
//            }
                return;
            }

            logger.info("第五步：计算工序1提成");
            map.put("TCJE1",execExpress(TCFormula.DJSGTCZD_TCJE1,map));

            logger.info("第六步：计算工序1提成比例/固定金额");
            map.put("TCBL_JE1",execExpress(TCFormula.DJSGTCZD_TCBL_JE1,map));

            logger.info("第七步：计算工序2提成");
            map.put("TCJE2",execExpress(TCFormula.DJSGTCZD_TCJE2,map));

            logger.info("第八步：计算工序2提成比例/固定金额");
            map.put("TCBL_JE2",execExpress(TCFormula.DJSGTCZD_TCBL_JE2,map));

            logger.info("第九步：计算工序3提成");
            map.put("TCJE3",execExpress(TCFormula.DJSGTCZD_TCJE3,map));

            logger.info("第十步：计算工序3提成比例/固定金额");
            map.put("TCBL_JE3",execExpress(TCFormula.DJSGTCZD_TCBL_JE3,map));

            logger.info("第十一步：计算工序4提成");
            map.put("TCJE4",execExpress(TCFormula.DJSGTCZD_TCJE4,map));

            logger.info("第十二步：计算工序4提成比例/固定金额");
            map.put("TCBL_JE4",execExpress(TCFormula.DJSGTCZD_TCBL_JE4,map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入单据施工提成参数" + jsonObject.toString());
            dao.insertDJSGTC(jsonObject);
            //回写提成到营业额明细
//            RetailOrderItem retailOrderItem = retailOrderItemRepository.findByOriginnumber(map.get("RETAIL_ITEM_ID").toString());
//            TurnoverDetails turnoverDetails = turnoverDetailsRepository.findByOriginAndOriginItem(retailOrderItem.getOrder().getId(),retailOrderItem.getId());
//            if(turnoverDetails != null){
//                turnoverDetails.setWorker(map.get("THE_WORKER").toString());
//                turnoverDetails.setWorkCommission(Arith.round(Double.parseDouble(map.get("TCJE1").toString()) + Double.parseDouble(map.get("TCJE2").toString()) + Double.parseDouble(map.get("TCJE3").toString()) + Double.parseDouble(map.get("TCJE4").toString()),2));
//                turnoverDetailsRepository.saveAndFlush(turnoverDetails);
//            }
            logger.info("开始计算人员施工提成");
            try {
                execRYSGTC(map);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        });
    }


    /**
     * 执行单据施工提成 整单内协和工单内协负单
     */
    public void execDJSGTCNXFD (JSONObject param){
        logger.info("开始执行单据施工提成整单内协和工单内协负单>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryDJSGTC_NXFD(param);
        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);
            logger.info("第一步：判断是否要计算提成");
            if (!dao.existDJSGTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;
            jsonObject = new JSONObject(map);
            if(map.get("OLDTCJE1") == null && map.get("OLDSALE_QTY") == null) return;
            map.put("TCJE1",execExpress("OLDTCJE1 / OLDSALE_QTY * SALE_QTY",map));
            map.put("TCJE2",execExpress("OLDTCJE2 / OLDSALE_QTY * SALE_QTY",map));
            map.put("TCJE3",execExpress("OLDTCJE3 / OLDSALE_QTY * SALE_QTY",map));
            map.put("TCJE4",execExpress("OLDTCJE4 / OLDSALE_QTY * SALE_QTY",map));
            map.put("TCBL_JE1",0);
            map.put("TCBL_JE2",0);
            map.put("TCBL_JE3",0);
            map.put("TCBL_JE4",0);
            jsonObject = new JSONObject(map);
            logger.info("执行写入单据施工提成参数" + jsonObject.toString());
            dao.insertDJSGTC(jsonObject);
            //回写提成到营业额明细
            //方案明细关联来源明细编号
//            RetailOrderItem retailItem = retailOrderItemRepository.findByOriginnumber(map.get("RETAIL_ITEM_ID").toString());
//            //零售退货明细查询原零售明细
//            RetailReturnItem returnItem = retailReturnItemRepository.findByRetailOrderItem(retailItem);
//            //零售退货明细关联来源明细编号
//            RetailOrderItem item = retailOrderItemRepository.findByOriginnumber(returnItem.getId());
//            TurnoverDetails turnoverDetails = turnoverDetailsRepository.findByOriginAndOriginItem(item.getOrder().getId(),item.getId());
//            if(turnoverDetails != null){
//                turnoverDetails.setWorker(map.get("THE_WORKER").toString());
//                turnoverDetails.setWorkCommission(Arith.round(Double.parseDouble(map.get("TCJE1").toString()) + Double.parseDouble(map.get("TCJE2").toString()) + Double.parseDouble(map.get("TCJE3").toString()) + Double.parseDouble(map.get("TCJE4").toString()),2));
//                turnoverDetailsRepository.saveAndFlush(turnoverDetails);
//            }
            logger.info("开始计算人员施工提成");
            try {
                execRYSGTC(map);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        });
    }



    /**
     * 执行分销单据施工提成 非定损
     */
    public void execFXDJSGTCFDS (JSONObject param){
        logger.info("开始执行分销单据施工提成非定损>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryFXDJSGTC_FDS(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existDJSGTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：取TC03施工提成规则");
            JSONObject TC03 = getStrategy(map, "TC03");
            //检查策略是否有取到 没有初始化字段默认值为0
            dao.checkField(TC03,"T101","T102");

            logger.info("第三步：取TC04工序提成规则");
            JSONObject TC04 = getStrategy(map, "TC04");
            //检查策略是否有取到 没有初始化字段默认值为0
            dao.checkField(TC04,"T111","T121","T112","T122","T113","T123","T114","T124");

            map.putAll(TC03);
            map.putAll(TC04);

            logger.info("第四步：判断是否要计算提成");
            if (map.get("T101").equals(0) && map.get("T102").equals(0) && map.get("T111").equals(0) && map.get("T121").equals(0)
                    && map.get("T112").equals(0) && map.get("T122").equals(0) && map.get("T113").equals(0)
                    && map.get("T123").equals(0) && map.get("T114").equals(0) && map.get("T124").equals(0)){
                //回写施工人到营业额明细
                writeBackCommission(map,"workCommission",false,map.get("RETAIL_ORDER_ID").toString());
                return;
            }

            logger.info("第五步：计算工序1提成");
            map.put("TCJE1",execExpress(TCFormula.FXDJSGTC_TCJE1,map));
            logger.info("第六步：计算工序1提成比例/固定金额");
            map.put("TCBL_JE1",execExpress(TCFormula.FXDJSGTCZD_TCBL_JE1,map));

            logger.info("第六步：计算工序2提成");
            map.put("TCJE2",execExpress(TCFormula.FXDJSGTC_TCJE2,map));
            logger.info("第六步：计算工序2提成比例/固定金额");
            map.put("TCBL_JE2",execExpress(TCFormula.FXDJSGTCZD_TCBL_JE2,map));

            logger.info("第七步：计算工序3提成");
            map.put("TCJE3",execExpress(TCFormula.FXDJSGTC_TCJE3,map));
            logger.info("第六步：计算工序3提成比例/固定金额");
            map.put("TCBL_JE3",execExpress(TCFormula.FXDJSGTCZD_TCBL_JE3,map));

            logger.info("第八步：计算工序4提成");
            map.put("TCJE4",execExpress(TCFormula.FXDJSGTC_TCJE4,map));
            logger.info("第六步：计算工序4提成比例/固定金额");
            map.put("TCBL_JE4",execExpress(TCFormula.FXDJSGTCZD_TCBL_JE4,map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入单据施工提成参数" + jsonObject.toString());
            dao.insertDJSGTC(jsonObject);
            //回写提成到营业额明细
            writeBackCommission(map,"workCommission",true,map.get("RETAIL_ORDER_ID").toString());
            logger.info("开始计算人员施工提成");
            try {
                execRYSGTC(map);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        });
    }


    /**
     * 执行分销单据施工提成 非定损负单
     */
    public void execFXDJSGTCFDSFD (JSONObject param){
        logger.info("开始执行分销单据施工提成非定损负单>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryFXDJSGTC_FDSFD(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existDJSGTCFXFD(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第五步：计算工序1提成");
            map.put("TCJE1",execExpress("OLD_TCJE1/OLD_SALE_QTY * SALE_QTY",map));

            logger.info("第六步：计算工序2提成");
            map.put("TCJE2",execExpress("OLD_TCJE2/OLD_SALE_QTY * SALE_QTY",map));

            logger.info("第七步：计算工序3提成");
            map.put("TCJE3",execExpress("OLD_TCJE3/OLD_SALE_QTY * SALE_QTY",map));

            logger.info("第八步：计算工序4提成");
            map.put("TCJE4",execExpress("OLD_TCJE4/OLD_SALE_QTY * SALE_QTY",map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入单据施工提成参数" + jsonObject.toString());
            dao.insertDJSGTC(jsonObject);
            //回写提成到营业额明细
            writeBackCommission(map,"workCommission",true,map.get("THE_RETAIL_ORDER_ID").toString());
            logger.info("开始计算人员施工提成");
            try {
                execRYSGTC(map);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        });
    }


    /**
     * 执行分销单据施工提成 定损
     */
    public void execFXDJSGTCDS (JSONObject param){
        logger.info("开始执行分销单据施工提成定损>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryFXDJSGTC_DS(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existDJSGTC(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第二步：取TC03施工提成规则");
            JSONObject TC03 = getStrategy(map, "TC03");
            //检查策略是否有取到 没有初始化字段默认值为0
            dao.checkField(TC03,"T101","T102");

            logger.info("第三步：取TC04工序提成规则");
            JSONObject TC04 = getStrategy(map, "TC04");
            //检查策略是否有取到 没有初始化字段默认值为0
            dao.checkField(TC04,"T111","T121","T112","T122","T113","T123","T114","T124");

            map.putAll(TC03);
            map.putAll(TC04);

            logger.info("第四步：判断是否要计算提成");
            if (map.get("T101").equals(0) && map.get("T102").equals(0) && map.get("T111").equals(0) && map.get("T121").equals(0)
                    && map.get("T112").equals(0) && map.get("T122").equals(0) && map.get("T113").equals(0)
                    && map.get("T123").equals(0) && map.get("T114").equals(0) && map.get("T124").equals(0)){
                //回写施工人到营业额明细
                writeBackCommission(map,"workCommission",false,map.get("RETAIL_ORDER_ID").toString());
                return;
            }

            logger.info("第五步：计算工序1提成");
            map.put("TCJE1",execExpress(TCFormula.FXDJSGTC_TCJE1,map));
            logger.info("第六步：计算工序1提成比例/固定金额");
            map.put("TCBL_JE1",execExpress(TCFormula.FXDJSGTCZD_TCBL_JE1,map));

            logger.info("第六步：计算工序2提成");
            map.put("TCJE2",execExpress(TCFormula.FXDJSGTC_TCJE2,map));
            logger.info("第六步：计算工序2提成比例/固定金额");
            map.put("TCBL_JE2",execExpress(TCFormula.FXDJSGTCZD_TCBL_JE2,map));

            logger.info("第七步：计算工序3提成");
            map.put("TCJE3",execExpress(TCFormula.FXDJSGTC_TCJE3,map));
            logger.info("第六步：计算工序3提成比例/固定金额");
            map.put("TCBL_JE3",execExpress(TCFormula.FXDJSGTCZD_TCBL_JE3,map));

            logger.info("第八步：计算工序4提成");
            map.put("TCJE4",execExpress(TCFormula.FXDJSGTC_TCJE4,map));
            logger.info("第六步：计算工序4提成比例/固定金额");
            map.put("TCBL_JE4",execExpress(TCFormula.FXDJSGTCZD_TCBL_JE4,map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入单据施工提成参数" + jsonObject.toString());
            dao.insertDJSGTC(jsonObject);
            //回写提成到营业额明细
            writeBackCommission(map,"workCommission",true,map.get("RETAIL_ORDER_ID").toString());
            logger.info("开始计算人员施工提成");
            try {
                execRYSGTC(map);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        });
    }

    /**
     * 执行分销单据施工提成 定损负单
     */
    public void execFXDJSGTCDSFD (JSONObject param){
        logger.info("开始执行分销单据施工提成定损负单>>>>>>>>>>>>>>>>>>>" + param.get("BILL_ID"));
        List<Map> maps = dao.queryFXDJSGTC_DSFD(param);

        maps.stream().forEach(map -> {
            JSONObject jsonObject = new JSONObject(map);

            logger.info("第一步：判断是否要计算提成");
            if (!dao.existDJSGTCFXFD(jsonObject).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

            logger.info("第五步：计算工序1提成");
            map.put("TCJE1",execExpress("OLD_TCJE1/OLD_SALE_QTY * SALE_QTY",map));

            logger.info("第六步：计算工序2提成");
            map.put("TCJE2",execExpress("OLD_TCJE2/OLD_SALE_QTY * SALE_QTY",map));

            logger.info("第七步：计算工序3提成");
            map.put("TCJE3",execExpress("OLD_TCJE3/OLD_SALE_QTY * SALE_QTY",map));

            logger.info("第八步：计算工序4提成");
            map.put("TCJE4",execExpress("OLD_TCJE4/OLD_SALE_QTY * SALE_QTY",map));

            jsonObject = new JSONObject(map);

            logger.info("执行写入单据施工提成参数" + jsonObject.toString());
            dao.insertDJSGTC(jsonObject);
            //回写提成到营业额明细
            writeBackCommission(map,"workCommission",true,map.get("THE_RETAIL_ORDER_ID").toString());
            logger.info("开始计算人员施工提成");
            try {
                execRYSGTC(map);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        });
    }

    /**
     * 人员施工提成
     * @param map 单据施工提成数据
     */
    public void execRYSGTC(Map map) throws Exception{
        for (int i = 1; i <= 4; i++) {
            String WORKER = (String) map.get("WORKER" + i);
            if (WORKER == null) continue;

            //将工序人员转成JSONArray
            com.apestech.framework.json.JSONArray workerArray = JSON.toJSONArray(WORKER);

            Map current = new HashMap();

            current.put("WORKER_COUNT",workerArray.size());

            logger.info("获取工序" + i + "提成金额");
            current.put("TCJE",map.get("TCJE"+i));
            current.put("WORKER_ARRAY",workerArray);
            current.put("CLASSIFY_ID",map.get("CLASSIFY_ID"));

            logger.info("获取工序" + i + "人员总份数");
            current.put("SUM_FS",dao.queryRYFS(new JSONObject(current)).getJSONObject(0).getInteger("PORTION"));

            for (int a = 0; a < workerArray.size(); a++) {
                JSONObject jsonObject = workerArray.getJSONObject(a);

                logger.info("计算平均提成");
                current.put("PJTC",execExpress("TCJE / WORKER_COUNT",current));

                logger.info("获取人员提成份数");
                current.put("PORTION",getOutPortion(jsonObject));

                logger.info("计算提成金额");
                current.put("TC_AMT",execExpress(TCFormula.RYSGTC_TCJE,current));

                current.put("WORKER",jsonObject.get("id"));
                current.put("PROCESS",i);

                current.putAll(map);
                logger.info("判断是否要计算提成");
                if (!dao.existRYSGTC(new JSONObject(current)).getJSONObject(0).get("CZBJ").toString().equals("0")) return;

                current.put("ID",dao.queryRYSGTCID(jsonObject).getJSONObject(0).getString("ID"));

                logger.info("执行写入人员施工提成参数" + new JSONObject(current).toString());
                dao.insertRYSGTC(new JSONObject(current));
            }
        }
    }

    private void writeBackCommission(Map map,String orderType,boolean valid,String retailOrderId){
        //回写提成到营业额明细
        TurnoverDetails turnoverDetails = turnoverDetailsRepository.findByOriginAndOriginItem(retailOrderId, map.get("RETAIL_ITEM_ID").toString());
        if(turnoverDetails != null){
            if("saleCommission".equals(orderType)){
                if(map.get("MAIN_SALESMAN") != null) turnoverDetails.setMainSalesman(partyRoleRepository.findOne(map.get("MAIN_SALESMAN").toString()));
                if(map.get("SUB_SALESMAN") != null) turnoverDetails.setSubSalesman(partyRoleRepository.findOne(map.get("SUB_SALESMAN").toString()));
                if(valid) turnoverDetails.setSaleCommission(Arith.round(Double.parseDouble(map.get("TCJE").toString()),2) + turnoverDetails.getSaleCommission());
            } else if("workCommission".equals(orderType)){
                turnoverDetails.setWorker(map.get("THE_WORKER").toString());
                if(valid) turnoverDetails.setWorkCommission(Arith.round(Double.parseDouble(map.get("TCJE1").toString()) + Double.parseDouble(map.get("TCJE2").toString()) + Double.parseDouble(map.get("TCJE3").toString()) + Double.parseDouble(map.get("TCJE4").toString()),2));
            }
            turnoverDetails.setOriginUpdateDate(new Date());
            turnoverDetailsRepository.saveAndFlush(turnoverDetails);
        }
    }

    public Integer getOutPortion(JSONObject jsonObject) throws Exception{
        com.apestech.framework.json.JSONArray workerArray = new com.apestech.framework.json.JSONArray();
        workerArray.add(jsonObject);
        jsonObject.put("WORKER_ARRAY",workerArray);
        return dao.queryRYFS(jsonObject).getJSONObject(0).getInteger("PORTION");
    }

    /**
     * 公式运算
     * @param formula 公式
     * @param value 参数
     * @return 默认值0
     * @throws Exception 公式异常
     */
    public BigDecimal execExpress(String formula, Map<String, Object> value) {
        try {
            if (TCExpressUtil.execute(formula, value) != null) {
                return new BigDecimal(TCExpressUtil.execute(formula, value).toString());
            }
        }catch (Exception e){
            throw new RuntimeException("检查公式["+formula+"]正确性\n"+e.toString());

        }
        return BigDecimal.valueOf(0);
    }

    /**
     * 策略调用
     */
    public JSONObject getStrategy(Map map,String conditionId){
        map.put("SYS_RQ",new Date());
        map.put("conditionId",conditionId);
        Object obj = this.invoke("condition.getCondition", map);
        Map resultMap = MapUtil.mapped(obj);
        JSONObject result = new JSONObject(resultMap);
        return result;
    }

    /**
     * 根据列名获取对应字段的值为空给 默认值 0
     */
    public BigDecimal checkAmtField(JSONArray array,String column){
        if (array.isEmpty() && array.size() == 0) return BigDecimal.valueOf(0);
        return array.getJSONObject(0).getString(column) == null ? BigDecimal.valueOf(0) : new BigDecimal(array.getJSONObject(0).getString(column));
    }

    private void saveXSTCLog(String payload) {
        Document document = new Document();
        document.put("payload", payload);
        document.put("date", LocalDateTime.now());
        mongoTemplate.getCollection("xstcConnection").insertOne(document);
    }

    private void saveSGTCLog(String payload) {
        Document document = new Document();
        document.put("payload", payload);
        document.put("date", LocalDateTime.now());
        mongoTemplate.getCollection("sgtcConnection").insertOne(document);
    }
}
